package com.yyfax.infrastructure.mvp;

import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.widget.Toast;

import com.trello.rxlifecycle.components.support.RxAppCompatActivity;
import com.yyfax.common.CLog;
import com.yyfax.common.tools.RobolectricUtils;
import com.yyfax.infrastructure.Constants;
import com.yyfax.infrastructure.R;
import com.yyfax.infrastructure.statistics.StatService;

import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeoutException;

import rx.Observable;

/**
 * Created by HenryZhang on 2017/2/23.
 * Copyright © 2017 www.yylending.com. All Rights Reserved.
 * <p>
 * RxAppCompatActivity会监听Activity的销毁事件，通过使用compose()在流中加入拦截器，
 * 效果：在subscribe()之前拦截Observable并检测Activity是否销毁，如果已销毁则中断Observable且取消订阅。
 */
public abstract class ViewActivity extends RxAppCompatActivity implements IView, LoaderManager.LoaderCallbacks<Presenter> {
	private static final String TAG = ViewActivity.class.getSimpleName();

	private final static int BASE_LOADER_ID = 999999;

	protected int mTimeout = R.string.check_network, mConnect = R.string.check_network,
			mError = R.string.check_network, mProgressMsgStrId = R.string.base_operating;

	protected ProgressDialog mProgressDialog;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		getSupportLoaderManager().initLoader(BASE_LOADER_ID, null, this);
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		getSupportLoaderManager().destroyLoader(BASE_LOADER_ID);
	}

	/**
	 * @param loader      the PresenterLoader</br>
	 * @param data        the Presenter instance just created</br>
	 * @param placeholder just use to override LoaderManager.Callback.onCreateLoader</br>
	 */
	public abstract void onLoadFinished(Loader<Presenter> loader, Presenter data, int placeholder);

	@Override
	public void onLoadFinished(Loader<Presenter> loader, Presenter data) {
		data.attachBaseView(this);
		switch (loader.getId()) {
			case BASE_LOADER_ID:
				break;
			default:
				onLoadFinished(loader, data, -1);
				break;
		}
	}

	@Override
	public void onLoaderReset(Loader<Presenter> loader) {
	}

	@Override
	public Observable.Transformer composeLifecycle() {
		return bindToLifecycle();
	}

	@Override
	public void onFunctionStart(final boolean autoTips) {
		runOnUiThread(new Runnable() {
			@Override
			public void run() {
				onFunctionalStart(autoTips);
			}
		});
	}

	@Override
	public void onFunctionCompleted(final boolean autoTips) {
		runOnUiThread(new Runnable() {
			@Override
			public void run() {
				onFunctionalCompleted(autoTips);
			}
		});
	}

	@Override
	public void onFunctionError(final Throwable e, final boolean autoTips, final int functionalCode) {
		runOnUiThread(new Runnable() {
			@Override
			public void run() {
				onFunctionalError(e, autoTips, functionalCode);
			}
		});
	}

	public void onFunctionalStart(boolean autoTips) {
		if (autoTips)
			showLoading(true);
	}

	public void onFunctionalCompleted(boolean autoTips) {
		if (autoTips)
			dismissLoading();
	}

	public void onFunctionalError(Throwable e, boolean autoTips, int functionalCode) {
		Map<String, String> body = new HashMap<>();
		body.put("functionalCode", functionalCode + "");
		body.put("msg", e.toString());
		StatService.onEventValue(this, "NetworkError", body, 0);
		showErrorToast(e);
		dismissLoading();
	}

	protected void showLoading(final boolean cancelable) {
		runOnUiThread(new Runnable() {
			@Override
			public void run() {
//				boolean isUI = (Thread.currentThread() == android.os.Looper.getMainLooper().getThread());
				CLog.d(TAG, "showLoading().cancelable=" + cancelable);
				//todo 临时适配robolectric（只在调用mainActivityOnStartTest时报异常）
				if (RobolectricUtils.isARobolectricUnitTest()) {
					if (mProgressDialog != null && mProgressDialog.isShowing()) {
						mProgressDialog.dismiss();
						mProgressDialog = null;
					}
					initProgressDialog(cancelable);
					mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
						@Override
						public void onCancel(DialogInterface dialog) {
						}
					});
					mProgressDialog.show();
					return;
				}
				//正常流程
				if (mProgressDialog == null) {
					initProgressDialog(cancelable);
				} else {
					if (!mProgressDialog.isShowing()) {
						mProgressDialog.setCanceledOnTouchOutside(cancelable);
						mProgressDialog.setCancelable(cancelable);
					}
				}
				if (!mProgressDialog.isShowing()) {
					mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
						@Override
						public void onCancel(DialogInterface dialog) {
						}
					});
					mProgressDialog.show();
				}
			}
		});
	}

	public void progressDialogCancel(DialogInterface dialog) {}

	protected void dismissLoading() {
		runOnUiThread(new Runnable() {
			@Override
			public void run() {
				CLog.d(TAG, "dismissLoading()");
				if (mProgressDialog != null && mProgressDialog.isShowing()) {
					mProgressDialog.dismiss();
				}
			}
		});
	}

	protected void showErrorToast(final Throwable e) {
		runOnUiThread(new Runnable() {
			@Override
			public void run() {
				CLog.d(TAG, "showErrorToast()");
				if (e instanceof UnknownHostException) {//无网络
				} else if (e instanceof SocketTimeoutException || e instanceof TimeoutException) {
					Toast.makeText(ViewActivity.this, mTimeout, Toast.LENGTH_SHORT).show();
					CLog.i(TAG, "onError(): SocketTimeoutException");
				} else if (e instanceof ConnectException) {
					Toast.makeText(ViewActivity.this, mConnect, Toast.LENGTH_SHORT).show();
					CLog.i(TAG, "onError(): ConnectException");
				} else {
					Toast.makeText(ViewActivity.this, mError, Toast.LENGTH_SHORT).show();
					CLog.i(TAG, "onError(): " + (e != null ? e.getMessage() : ""));
					if (e != null && Constants.DEBUG_TOGGLE)
						e.printStackTrace();
				}
			}
		});
	}

	protected void initProgressDialog(boolean cancelable) {
		mProgressDialog = new ProgressDialog(this);
		mProgressDialog.setMessage(getString(mProgressMsgStrId));
		mProgressDialog.setCanceledOnTouchOutside(cancelable);
		mProgressDialog.setCancelable(cancelable);
		mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
			@Override
			public void onCancel(DialogInterface dialog) {
				mProgressDialog.dismiss();
			}
		});
	}
}
